﻿using SD.Common;
using SD.Infrastructure.EntityBase;
using SD.Toolkits.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlamDunk.ValueObjects.Enums;
using SlamDunk.ValueObjects.Structs;

namespace SlamDunk.MES.Domain.Entities.ExecutionContext
{
    /// <summary>
    /// 工单
    /// </summary>
    public class WorkOrder : AggregateRootEntity
    {
        #region # 构造器

        #region 00.无参构造器
        /// <summary>
        /// 无参构造器
        /// </summary>
        protected WorkOrder()
        {
            //初始化导航属性
            this.PersonAsks = new HashSet<WorkOrderPersonAsk>();
            this.EquipmentAsks = new HashSet<WorkOrderEquipmentAsk>();
            this.MaterialAsks = new HashSet<WorkOrderMaterialAsk>();
            this.ParameterAsks = new HashSet<WorkOrderParameterAsk>();
            this.ActualPersons = new HashSet<WorkOrderActualPerson>();
            this.ActualEquipments = new HashSet<WorkOrderActualEquipment>();
            this.ActualMaterials = new HashSet<WorkOrderActualMaterial>();
            this.ActualParameters = new HashSet<WorkOrderActualParameter>();

            //默认值
            this.Status = WorkOrderStatus.Ready;
            this.HasInspected = null;
        }
        #endregion

        #region 01.创建工单构造器
        /// <summary>
        /// 创建工单构造器
        /// </summary>
        /// <param name="workOrderNo">工单编号</param>
        /// <param name="workOrderName">工单名称</param>
        /// <param name="productionPlanId">生产计划Id</param>
        /// <param name="executionPlanId">作业计划Id</param>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <param name="durationQuota">工时定额</param>
        /// <param name="directivePath">工艺指导书</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="workStationId">工位Id</param>
        /// <param name="formMode">表单模式</param>
        /// <param name="formDefinition">表单定义</param>
        /// <param name="needToInspect">是否需质检</param>
        /// <param name="sort">排序</param>
        /// <param name="description">描述</param>
        public WorkOrder(string workOrderNo, string workOrderName, Guid? productionPlanId, Guid executionPlanId, Guid processSegmentId, TimeSpan durationQuota, string directivePath, Guid? facilityId, Guid? workStationId, FormMode formMode, FormDefinition formDefinition, bool needToInspect, int sort, string description)
            : this()
        {
            base.Number = workOrderNo;
            base.Name = workOrderName;
            this.ProductionPlanId = productionPlanId;
            this.ExecutionPlanId = executionPlanId;
            this.ProcessSegmentId = processSegmentId;
            this.DurationQuotaTicks = durationQuota.Ticks;
            this.DirectivePath = directivePath;
            this.FacilityId = facilityId;
            this.WorkStationId = workStationId;
            this.FormMode = formMode;
            this.FormDefinitionStr = formDefinition?.ToJson();
            this.NeedToInspect = needToInspect;
            this.Sort = sort;
            this.Description = description;

            //如需质检，设置未质检
            if (this.NeedToInspect)
            {
                this.HasInspected = false;
            }

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #endregion

        #region # 属性

        #region 生产计划Id —— Guid? ProductionPlanId
        /// <summary>
        /// 生产计划Id
        /// </summary>
        public Guid? ProductionPlanId { get; private set; }
        #endregion

        #region 作业计划Id —— Guid ExecutionPlanId
        /// <summary>
        /// 作业计划Id
        /// </summary>
        public Guid ExecutionPlanId { get; private set; }
        #endregion

        #region 工艺段Id —— Guid ProcessSegmentId
        /// <summary>
        /// 工艺段Id
        /// </summary>
        public Guid ProcessSegmentId { get; private set; }
        #endregion

        #region 工时定额 —— TimeSpan DurationQuota
        /// <summary>
        /// 工时定额
        /// </summary>
        public long DurationQuotaTicks { get; private set; }


        /// <summary>
        /// 工时定额
        /// </summary>
        public TimeSpan DurationQuota
        {
            get => TimeSpan.FromTicks(this.DurationQuotaTicks);
        }
        #endregion

        #region 工艺指导书 —— string DirectivePath
        /// <summary>
        /// 工艺指导书
        /// </summary>
        /// <remarks>PDF路径</remarks>
        public string DirectivePath { get; private set; }
        #endregion

        #region 工厂模型Id —— Guid? FacilityId 
        /// <summary>
        /// 工厂模型Id
        /// </summary>
        public Guid? FacilityId { get; private set; }
        #endregion

        #region 工位Id —— Guid? WorkStationId 
        /// <summary>
        /// 工位Id
        /// </summary>
        public Guid? WorkStationId { get; private set; }
        #endregion

        #region 表单模式 —— FormMode FormMode
        /// <summary>
        /// 表单模式
        /// </summary>
        public FormMode FormMode { get; private set; }
        #endregion

        #region 表单定义 —— FormDefinition FormDefinition
        /// <summary>
        /// 只读属性 - 表单定义
        /// </summary>
        public FormDefinition FormDefinition
        {
            get
            {
                return string.IsNullOrWhiteSpace(this.FormDefinitionStr)
                    ? null
                    : this.FormDefinitionStr.AsJsonTo<FormDefinition>();
            }
        }

        /// <summary>
        /// 内部属性 - 表单定义
        /// </summary>
        public string FormDefinitionStr { get; private set; }
        #endregion

        #region 表单实例 —— string FormInstance
        /// <summary>
        /// 表单实例
        /// </summary>
        public string FormInstance { get; private set; }
        #endregion

        #region 工单状态 —— WorkOrderStatus Status
        /// <summary>
        /// 工单状态
        /// </summary>
        public WorkOrderStatus Status { get; private set; }
        #endregion

        #region 异常原因 —— string ExceptionReason
        /// <summary>
        /// 异常原因
        /// </summary>
        public string ExceptionReason { get; private set; }
        #endregion

        #region 分派班组Id —— Guid? DispatchedTeamId
        /// <summary>
        /// 分派班组Id
        /// </summary>
        public Guid? DispatchedTeamId { get; private set; }
        #endregion

        #region 分派人员Id —— Guid? DispatchedPersonId
        /// <summary>
        /// 分派人员Id
        /// </summary>
        public Guid? DispatchedPersonId { get; private set; }
        #endregion

        #region 实际开始时间 —— DateTime? ActualStartTime
        /// <summary>
        /// 实际开始时间
        /// </summary>
        public DateTime? ActualStartTime { get; private set; }
        #endregion

        #region 实际结束时间 —— DateTime? ActualEndTime
        /// <summary>
        /// 实际结束时间
        /// </summary>
        public DateTime? ActualEndTime { get; private set; }
        #endregion

        #region 是否需质检 —— bool NeedToInspect
        /// <summary>
        /// 是否需质检
        /// </summary>
        public bool NeedToInspect { get; private set; }
        #endregion

        #region 是否已质检 —— bool? HasInspected
        /// <summary>
        /// 是否已质检
        /// </summary>
        public bool? HasInspected { get; private set; }
        #endregion

        #region 排序 —— int Sort
        /// <summary>
        /// 排序
        /// </summary>
        public int Sort { get; private set; }
        #endregion

        #region 描述 —— string Description
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        #endregion

        #region 导航属性 - 工单人员要求集 —— ICollection<WorkOrderPersonAsk> PersonAsks
        /// <summary>
        /// 导航属性 - 工单人员要求集
        /// </summary>
        public virtual ICollection<WorkOrderPersonAsk> PersonAsks { get; private set; }
        #endregion

        #region 导航属性 - 工单设备要求集 —— ICollection<WorkOrderEquipmentAsk> EquipmentAsks
        /// <summary>
        /// 导航属性 - 工单设备要求集
        /// </summary>
        public virtual ICollection<WorkOrderEquipmentAsk> EquipmentAsks { get; private set; }
        #endregion

        #region 导航属性 - 工单物料要求集 —— ICollection<WorkOrderMaterialAsk> MaterialAsks
        /// <summary>
        /// 导航属性 - 工单物料要求集
        /// </summary>
        public virtual ICollection<WorkOrderMaterialAsk> MaterialAsks { get; private set; }
        #endregion

        #region 导航属性 - 工单参数要求集 —— ICollection<WorkOrderParameterAsk> ParameterAsks
        /// <summary>
        /// 导航属性 - 工单参数要求集
        /// </summary>
        public virtual ICollection<WorkOrderParameterAsk> ParameterAsks { get; private set; }
        #endregion

        #region 导航属性 - 工单实际人员集 —— ICollection<WorkOrderActualPerson> ActualPersons
        /// <summary>
        /// 导航属性 - 工单实际人员集
        /// </summary>
        public virtual ICollection<WorkOrderActualPerson> ActualPersons { get; private set; }
        #endregion

        #region 导航属性 - 工单实际设备集 —— ICollection<WorkOrderActualEquipment> ActualEquipments
        /// <summary>
        /// 导航属性 - 工单实际设备集
        /// </summary>
        public virtual ICollection<WorkOrderActualEquipment> ActualEquipments { get; private set; }
        #endregion

        #region 导航属性 - 工单实际物料集 —— ICollection<WorkOrderActualMaterial> ActualMaterials
        /// <summary>
        /// 导航属性 - 工单实际物料集
        /// </summary>
        public virtual ICollection<WorkOrderActualMaterial> ActualMaterials { get; private set; }
        #endregion

        #region 导航属性 - 工单实际参数集 —— ICollection<WorkOrderActualParameter> ActualParameters
        /// <summary>
        /// 导航属性 - 工单实际参数集
        /// </summary>
        public virtual ICollection<WorkOrderActualParameter> ActualParameters { get; private set; }
        #endregion

        #endregion

        #region # 方法

        #region 修改工单 —— void UpdateInfo(string workOrderName, TimeSpan durationQuota...
        /// <summary>
        /// 修改工单
        /// </summary>
        /// <param name="workOrderName">工单名称</param>
        /// <param name="durationQuota">工时定额</param>
        /// <param name="directivePath">工艺指导书</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="workStationId">工位Id</param>
        /// <param name="needToInspect">是否需质检</param>
        /// <param name="sort">排序</param>
        /// <param name="description">描述</param>
        public void UpdateInfo(string workOrderName, TimeSpan durationQuota, string directivePath, Guid? facilityId, Guid? workStationId, bool needToInspect, int sort, string description)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以修改！");
            }

            #endregion

            base.Name = workOrderName;
            this.DurationQuotaTicks = durationQuota.Ticks;
            this.DirectivePath = directivePath;
            this.FacilityId = facilityId;
            this.WorkStationId = workStationId;
            this.NeedToInspect = needToInspect;
            this.Sort = sort;
            this.Description = description;

            //如需质检，设置未质检
            if (this.NeedToInspect)
            {
                this.HasInspected = false;
            }
            else
            {
                this.HasInspected = null;
            }

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #region 设置工单人员要求 —— void SetPersonAsks(IEnumerable<WorkOrderPersonAsk> personAsks)
        /// <summary>
        /// 设置工单人员要求
        /// </summary>
        /// <param name="personAsks">工单人员要求集</param>
        public void SetPersonAsks(IEnumerable<WorkOrderPersonAsk> personAsks)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以修改！");
            }

            #endregion

            personAsks = personAsks?.ToArray() ?? new WorkOrderPersonAsk[0];

            this.ClearPersonAsks();
            if (personAsks.Any())
            {
                this.PersonAsks.AddRange(personAsks);
                foreach (WorkOrderPersonAsk personAsk in personAsks)
                {
                    personAsk.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单设备要求 —— void SetEquipmentAsks(IEnumerable<WorkOrderEquipmentAsk> equipmentAsks)
        /// <summary>
        /// 设置工单设备要求
        /// </summary>
        /// <param name="equipmentAsks">工单设备要求集</param>
        public void SetEquipmentAsks(IEnumerable<WorkOrderEquipmentAsk> equipmentAsks)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以修改！");
            }

            #endregion

            equipmentAsks = equipmentAsks?.ToArray() ?? new WorkOrderEquipmentAsk[0];

            this.ClearEquipmentAsks();
            if (equipmentAsks.Any())
            {
                this.EquipmentAsks.AddRange(equipmentAsks);
                foreach (WorkOrderEquipmentAsk equipmentAsk in equipmentAsks)
                {
                    equipmentAsk.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单物料要求 —— void SetMaterialAsks(IEnumerable<WorkOrderMaterialAsk> materialAsks)
        /// <summary>
        /// 设置工单物料要求
        /// </summary>
        /// <param name="materialAsks">工单物料要求集</param>
        public void SetMaterialAsks(IEnumerable<WorkOrderMaterialAsk> materialAsks)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以修改！");
            }

            #endregion

            materialAsks = materialAsks?.ToArray() ?? new WorkOrderMaterialAsk[0];

            this.ClearMaterialAsks();
            if (materialAsks.Any())
            {
                this.MaterialAsks.AddRange(materialAsks);
                foreach (WorkOrderMaterialAsk materialAsk in materialAsks)
                {
                    materialAsk.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单参数要求 —— void SetParameterAsks(IEnumerable<WorkOrderParameterAsk> parameterAsks)
        /// <summary>
        /// 设置工单参数要求
        /// </summary>
        /// <param name="parameterAsks">工单参数要求集</param>
        public void SetParameterAsks(IEnumerable<WorkOrderParameterAsk> parameterAsks)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以修改！");
            }

            #endregion

            parameterAsks = parameterAsks?.ToArray() ?? new WorkOrderParameterAsk[0];

            this.ClearParameterAsks();
            if (parameterAsks.Any())
            {
                this.ParameterAsks.AddRange(parameterAsks);
                foreach (WorkOrderParameterAsk parameterAsk in parameterAsks)
                {
                    parameterAsk.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单实际人员 —— void SetActualPersons(IEnumerable<WorkOrderActualPerson> actualPersons)
        /// <summary>
        /// 设置工单实际人员
        /// </summary>
        /// <param name="actualPersons">工单实际人员集</param>
        public void SetActualPersons(IEnumerable<WorkOrderActualPerson> actualPersons)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Executing)
            {
                throw new InvalidOperationException("只有执行状态的工单可以设置工单实际人员！");
            }

            #endregion

            actualPersons = actualPersons?.ToArray() ?? new WorkOrderActualPerson[0];

            this.ClearActualPersons();
            if (actualPersons.Any())
            {
                this.ActualPersons.AddRange(actualPersons);
                foreach (WorkOrderActualPerson actualPerson in actualPersons)
                {
                    actualPerson.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单实际设备 —— void SetActualEquipments(IEnumerable<WorkOrderActualEquipment> actualEquipments)
        /// <summary>
        /// 设置工单实际设备
        /// </summary>
        /// <param name="actualEquipments">工单实际设备集</param>
        public void SetActualEquipments(IEnumerable<WorkOrderActualEquipment> actualEquipments)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Executing)
            {
                throw new InvalidOperationException("只有执行状态的工单可以设置工单实际设备！");
            }

            #endregion

            actualEquipments = actualEquipments?.ToArray() ?? new WorkOrderActualEquipment[0];

            this.ClearActualEquipments();
            if (actualEquipments.Any())
            {
                this.ActualEquipments.AddRange(actualEquipments);
                foreach (WorkOrderActualEquipment actualEquipment in actualEquipments)
                {
                    actualEquipment.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单实际物料投入 —— void SetActualInputMaterials(IEnumerable<WorkOrderActualMaterial> actualInputMaterials)
        /// <summary>
        /// 设置工单实际物料投入
        /// </summary>
        /// <param name="actualInputMaterials">工单实际投入物料集</param>
        public void SetActualInputMaterials(IEnumerable<WorkOrderActualMaterial> actualInputMaterials)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Executing)
            {
                throw new InvalidOperationException("只有执行状态的工单可以设置工单实际物料投入！");
            }

            actualInputMaterials = actualInputMaterials?.ToArray() ?? new WorkOrderActualMaterial[0];
            if (actualInputMaterials.Any(x => x.DirectionType != MaterialDirectionType.Input))
            {
                throw new ArgumentOutOfRangeException(nameof(actualInputMaterials), "工单实际物料必须是输入类型！");
            }

            #endregion

            this.ClearActualInputMaterials();
            if (actualInputMaterials.Any())
            {
                this.ActualMaterials.AddRange(actualInputMaterials);
                foreach (WorkOrderActualMaterial actualInputMaterial in actualInputMaterials)
                {
                    actualInputMaterial.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单实际物料产出 —— void SetActualOutputMaterials(IEnumerable<WorkOrderActualMaterial> actualOutputMaterials)
        /// <summary>
        /// 设置工单实际物料产出
        /// </summary>
        /// <param name="actualOutputMaterials">工单实际产出物料集</param>
        public void SetActualOutputMaterials(IEnumerable<WorkOrderActualMaterial> actualOutputMaterials)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Executing)
            {
                throw new InvalidOperationException("只有执行状态的工单可以设置工单实际物料产出！");
            }

            actualOutputMaterials = actualOutputMaterials?.ToArray() ?? new WorkOrderActualMaterial[0];
            if (actualOutputMaterials.Any(x => x.DirectionType != MaterialDirectionType.Output))
            {
                throw new ArgumentOutOfRangeException(nameof(actualOutputMaterials), "工单实际物料必须是输出类型！");
            }

            #endregion

            this.ClearActualOutputMaterials();
            if (actualOutputMaterials.Any())
            {
                this.ActualMaterials.AddRange(actualOutputMaterials);
                foreach (WorkOrderActualMaterial actualOutputMaterial in actualOutputMaterials)
                {
                    actualOutputMaterial.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 设置工单实际参数 —— void SetActualParameters(IEnumerable<WorkOrderActualParameter> actualParameters)
        /// <summary>
        /// 设置工单实际参数
        /// </summary>
        /// <param name="actualParameters">工单实际参数集</param>
        public void SetActualParameters(IEnumerable<WorkOrderActualParameter> actualParameters)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Executing)
            {
                throw new InvalidOperationException("只有执行状态的工单可以设置工单实际参数！");
            }

            #endregion

            actualParameters = actualParameters?.ToArray() ?? new WorkOrderActualParameter[0];

            this.ClearActualParameters();
            if (actualParameters.Any())
            {
                this.ActualParameters.AddRange(actualParameters);
                foreach (WorkOrderActualParameter actualParameter in actualParameters)
                {
                    actualParameter.WorkOrder = this;
                }
            }
        }
        #endregion

        #region 准备 —— void Ready()
        /// <summary>
        /// 准备
        /// </summary>
        public void Ready()
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Dispatched)
            {
                throw new InvalidOperationException("只有已分派的工单可以重新准备！");
            }

            #endregion

            this.Status = WorkOrderStatus.Ready;
            this.DispatchedTeamId = null;
            this.DispatchedPersonId = null;
        }
        #endregion

        #region 取消 —— void Cancel(string reason)
        /// <summary>
        /// 取消
        /// </summary>
        /// <param name="reason">取消原因</param>
        public void Cancel(string reason)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以取消！");
            }

            #endregion

            this.Status = WorkOrderStatus.Cancelled;
            this.ExceptionReason = reason;
        }
        #endregion

        #region 分派班组 —— void DispatchTeam(Guid teamId)
        /// <summary>
        /// 分派班组
        /// </summary>
        /// <param name="teamId">班组Id</param>
        public void DispatchTeam(Guid teamId)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以分派！");
            }

            #endregion

            this.DispatchedTeamId = teamId;
            this.Status = WorkOrderStatus.Dispatched;
        }
        #endregion

        #region 分派人员 —— void DispatchPerson(Guid personId)
        /// <summary>
        /// 分派人员
        /// </summary>
        /// <param name="personId">人员Id</param>
        public void DispatchPerson(Guid personId)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Ready)
            {
                throw new InvalidOperationException("只有准备状态的工单可以分派！");
            }

            #endregion

            this.DispatchedPersonId = personId;
            this.Status = WorkOrderStatus.Dispatched;
        }
        #endregion

        #region 执行 —— void Execute()
        /// <summary>
        /// 执行
        /// </summary>
        public void Execute()
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Dispatched && this.Status != WorkOrderStatus.Aborted)
            {
                throw new InvalidOperationException("只有已分派或已中止的工单可以执行！");
            }

            #endregion

            this.Status = WorkOrderStatus.Executing;
            if (!this.ActualStartTime.HasValue)
            {
                this.ActualStartTime = DateTime.Now;
            }
        }
        #endregion

        #region 中止 —— void Abort(string reason)
        /// <summary>
        /// 中止
        /// </summary>
        /// <param name="reason">中止原因</param>
        public void Abort(string reason)
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Dispatched && this.Status != WorkOrderStatus.Executing)
            {
                throw new InvalidOperationException("只有已分派或执行中的工单可以中止！");
            }

            #endregion

            this.Status = WorkOrderStatus.Aborted;
            this.ExceptionReason = reason;
        }
        #endregion

        #region 完成 —— void Complete()
        /// <summary>
        /// 完成
        /// </summary>
        public void Complete()
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Executing)
            {
                throw new InvalidOperationException("只有执行中的工单可以完成！");
            }

            #endregion

            this.Status = WorkOrderStatus.Completed;
            this.ActualEndTime = DateTime.Now;
        }
        #endregion

        #region 质检 —— void Inspect()
        /// <summary>
        /// 质检
        /// </summary>
        public void Inspect()
        {
            #region # 验证

            if (this.Status != WorkOrderStatus.Completed)
            {
                throw new InvalidOperationException("只有已完成的工单可以质检！");
            }

            #endregion

            this.HasInspected = true;
        }
        #endregion

        #region 清空人员要求 —— void ClearPersonAsks()
        /// <summary>
        /// 清空人员要求
        /// </summary>
        private void ClearPersonAsks()
        {
            foreach (WorkOrderPersonAsk personAsk in this.PersonAsks.ToArray())
            {
                this.PersonAsks.Remove(personAsk);
            }
        }
        #endregion

        #region 清空设备要求 —— void ClearEquipmentAsks()
        /// <summary>
        /// 清空设备要求
        /// </summary>
        private void ClearEquipmentAsks()
        {
            foreach (WorkOrderEquipmentAsk equipmentAsk in this.EquipmentAsks.ToArray())
            {
                this.EquipmentAsks.Remove(equipmentAsk);
            }
        }
        #endregion

        #region 清空物料要求 —— void ClearMaterialAsks()
        /// <summary>
        /// 清空物料要求
        /// </summary>
        private void ClearMaterialAsks()
        {
            foreach (WorkOrderMaterialAsk materialAsk in this.MaterialAsks.ToArray())
            {
                this.MaterialAsks.Remove(materialAsk);
            }
        }
        #endregion

        #region 清空参数要求 —— void ClearParameterAsks()
        /// <summary>
        /// 清空参数要求
        /// </summary>
        private void ClearParameterAsks()
        {
            foreach (WorkOrderParameterAsk parameterAsk in this.ParameterAsks.ToArray())
            {
                this.ParameterAsks.Remove(parameterAsk);
            }
        }
        #endregion

        #region 清空实际人员 —— void ClearActualPersons()
        /// <summary>
        /// 清空实际人员
        /// </summary>
        private void ClearActualPersons()
        {
            foreach (WorkOrderActualPerson actualPerson in this.ActualPersons.ToArray())
            {
                this.ActualPersons.Remove(actualPerson);
            }
        }
        #endregion

        #region 清空实际设备 —— void ClearActualEquipments()
        /// <summary>
        /// 清空实际设备
        /// </summary>
        private void ClearActualEquipments()
        {
            foreach (WorkOrderActualEquipment actualEquipment in this.ActualEquipments.ToArray())
            {
                this.ActualEquipments.Remove(actualEquipment);
            }
        }
        #endregion

        #region 清空实际物料投入 —— void ClearActualInputMaterials()
        /// <summary>
        /// 清空实际物料投入
        /// </summary>
        private void ClearActualInputMaterials()
        {
            foreach (WorkOrderActualMaterial actualMaterial in this.ActualMaterials.Where(x => x.DirectionType == MaterialDirectionType.Input).ToArray())
            {
                this.ActualMaterials.Remove(actualMaterial);
            }
        }
        #endregion

        #region 清空实际物料产出 —— void ClearActualOutputMaterials()
        /// <summary>
        /// 清空实际物料产出
        /// </summary>
        private void ClearActualOutputMaterials()
        {
            foreach (WorkOrderActualMaterial actualMaterial in this.ActualMaterials.Where(x => x.DirectionType == MaterialDirectionType.Output).ToArray())
            {
                this.ActualMaterials.Remove(actualMaterial);
            }
        }
        #endregion

        #region 清空实际参数 —— void ClearActualParameters()
        /// <summary>
        /// 清空实际参数
        /// </summary>
        private void ClearActualParameters()
        {
            foreach (WorkOrderActualParameter actualParameter in this.ActualParameters.ToArray())
            {
                this.ActualParameters.Remove(actualParameter);
            }
        }
        #endregion

        #region 初始化关键字 —— void InitKeywords()
        /// <summary>
        /// 初始化关键字
        /// </summary>
        private void InitKeywords()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(base.Number);
            builder.Append(base.Name);
            builder.Append(this.Description);

            base.SetKeywords(builder.ToString());
        }
        #endregion

        #endregion
    }
}
